package com.plat.api.api.action;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.plat.api.api.action.common.BuildOrderParam;
import com.plat.api.api.action.common.CommonMethod;
import com.plat.api.common.OrderType;
import com.plat.api.common.RespCode;
import com.plat.api.dao.api.*;
import com.plat.api.entity.api.*;
import com.plat.api.exception.PlatException;
import com.plat.api.mapper.PlatGoodMapper;
import com.plat.api.redis.RedisCache;
import com.plat.api.util.SnowflakeIdWorker;
import com.plat.api.util.YmalPropertiesUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created with IntelliJ IDEA.
 * User: shish
 * Date: 2020/9/10
 * Time: 23:30
 * Description: No Description
 */
@Service
public class PlatGoodsAction {
    @Autowired
    private UserDao userDao;
    @Autowired
    private TokenDao tokenDao;
    @Autowired
    private PlatGoodMapper platGoodMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private WxPayService wxService;
    @Autowired
    private PlatOrderDao platOrderDao;
    @Autowired
    private PlatOrderDetailDao platOrderDetailDao;
    @Autowired
    private PlatExpressAddressDao expressAddressDao;

    @Transactional(rollbackFor = Exception.class)
    public Object publish(JSONObject jsonObject) {
        String token = jsonObject.getJSONObject("head").getString("token");
        TokenEntity tokenEntity = tokenDao.getSQLManager().lambdaQuery(TokenEntity.class).andEq("token", token).single();
        UserEntity userEntity = userDao.getSQLManager().lambdaQuery(UserEntity.class).andEq("id", tokenEntity.getUserId()).single();
        JSONObject body = jsonObject.getJSONObject("body");
        PlatGoodsEntity goodEntity = new PlatGoodsEntity();
        goodEntity.setGoodsName(body.getString("detail"));
        goodEntity.setCategory("YSP");
        goodEntity.setGoodsDesc(body.getString("detail"));
        goodEntity.setGoodsStatus(1);
        goodEntity.setUserId(userEntity.getId());
        goodEntity.setUserName(userEntity.getNickname());
        goodEntity.setGoodsPrice(body.getDouble("price"));
        goodEntity.setDiscountPrice(0.0D);
        goodEntity.setCreateTime(new Date());
        goodEntity.setGoodsImage(body.getString("url"));
        goodEntity.setGoodsDeatail(body.getString("detail"));
        String goodsSn = RandomUtil.randomNumbers(11);
        goodEntity.setGoodsSn(goodsSn);
        goodEntity.setExpressFee((body.getDouble("expressFee")));
        goodEntity.setNum(body.getInteger("num"));
        goodEntity.setInitNum(body.getInteger("num"));
        platGoodMapper.insert(goodEntity);
        JSONObject json = new JSONObject();
        int num = body.getInteger("num");
        redisCache.setCacheObject(goodsSn, num);
        json.put("object", JSONObject.toJSON(goodEntity));
        return json;
    }

    public JSONObject getGoodsList(JSONObject jsonObject) {
        JSONObject body = jsonObject.getJSONObject("body");
        Integer page = body.getInteger("page");
        Integer pageSize = body.getInteger("pageSize");
        QueryWrapper<PlatGoodsEntity> wrapper = new QueryWrapper();
        wrapper.orderBy(true,false,"id");
        Page<PlatGoodsEntity> pa = new Page<>(page, pageSize);
        IPage<PlatGoodsEntity> iPage = platGoodMapper.selectPage(pa, wrapper);
        JSONObject result = new JSONObject();
        List<PlatGoodsEntity> list = iPage.getRecords();
        for (PlatGoodsEntity goodEntity : list) {
            int num;
            if (redisCache.hasKey(goodEntity.getGoodsSn())) {
                num = redisCache.getCacheObject(goodEntity.getGoodsSn());
            } else {
                num = 0;
            }
            goodEntity.setNum(num);
            NumberFormat numberFormat = NumberFormat.getInstance();
            numberFormat.setMaximumFractionDigits(2);
            if(goodEntity.getInitNum()==0){
                goodEntity.setInitNum(1);
            }
            String per = numberFormat.format((float) num / (float) goodEntity.getInitNum() * 100);
            goodEntity.setPercent(Double.valueOf(per).intValue());
        }
        result.put("list", list);
        return result;
    }

    public JSONObject createPay(JSONObject param) throws WxPayException {
        //查询有无默认地址
        UserEntity userEntity = CommonMethod.getUserEntity(tokenDao, userDao, param);
        PlatExpressAddressEntity addressEntity = expressAddressDao.createLambdaQuery().andEq("is_default", 1).andEq("user_id", userEntity.getId()).single();
        if (addressEntity == null) {
            throw new PlatException(RespCode.SELECT_ADDRESS.getCode(), "参加抢购请先设置默认收货地址");
        }
        JSONObject body = param.getJSONObject("body");
        String outTradeNo = SnowflakeIdWorker.getId();
        PlatOrderEntity order = new PlatOrderEntity();
        order.setDeliveryId(addressEntity.getId());
        QueryWrapper<PlatGoodsEntity> queryWrapper = new QueryWrapper();
        queryWrapper.eq("goods_sn", body.getString("goodsSn"));

        int num;
        if (redisCache.hasKey(body.getString("goodsSn"))) {
            num = redisCache.getCacheObject(body.getString("goodsSn"));
        } else {
            num = 0;
        }
        WxPayMpOrderResult wxPayMpOrderResult = null;
        PlatGoodsEntity goodsEntity = null;
        if (num - 1 >= 0) {
            redisCache.setCacheObject(body.getString("goodsSn"), num - 1);
            try {
                goodsEntity = platGoodMapper.selectOne(queryWrapper);
                WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
                request.setOpenid(userEntity.getOpenId());
                String payBody = StringUtils.substring(goodsEntity.getGoodsDesc(), 0, 25) + "...";
                request.setBody(payBody);
                request.setOutTradeNo(outTradeNo);
                Double p = goodsEntity.getGoodsPrice() * 100 + goodsEntity.getExpressFee() * 100;
                request.setTotalFee(p.intValue());
                request.setSpbillCreateIp("0.0.0.0");
                request.setNotifyUrl(YmalPropertiesUtil.getValue("wxpay.buy-goods-notify-url").toString());
                request.setTradeType("JSAPI");
                wxPayMpOrderResult = wxService.createOrder(request);
                BuildOrderParam buildOrderParam = new BuildOrderParam();
                buildOrderParam.setGoodsName(goodsEntity.getGoodsName());
                buildOrderParam.setGoodsDetail(goodsEntity.getGoodsDesc());
                buildOrderParam.setOrder(order);
                buildOrderParam.setPlatOrderDao(platOrderDao);
                buildOrderParam.setPlatOrderDetailDao(platOrderDetailDao);
                buildOrderParam.setUserEntity(userEntity);
                buildOrderParam.setOutTradeNo(outTradeNo);
                buildOrderParam.setPrice(goodsEntity.getGoodsPrice());
                buildOrderParam.setGoodsId(goodsEntity.getId());
                buildOrderParam.setOrderType(OrderType.YSP);
                buildOrderParam.setExpressFee(new BigDecimal(goodsEntity.getExpressFee()));
                CommonMethod.createOrder(buildOrderParam);
            } catch (Exception e) {
                //出错还原库存
                e.printStackTrace();
                redisCache.setCacheObject(body.getString("goodsSn"), num + 1);
            }
        } else {
            throw new PlatException("客官,来晚了，抢光了");
        }
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        String per = numberFormat.format((float) num / (float) goodsEntity.getInitNum() * 100);
        JSONObject json = new JSONObject();
        json.put("payInfo", wxPayMpOrderResult);
        Map<String, Object> map = new HashMap<>();
        map.put("goodsSn", body.getString("goodsSn"));
        map.put("num", num - 1);
        map.put("per", Double.valueOf(per).intValue());
        json.put("object", map);
        return json;
    }
}
